﻿using DLL.NET.DB.MS.Drugs.CRUD.Repository;
using DLL.NET50.DB.MS.Entity;
using DLL.NET50.DB.PIVAS.Entitys.DTO;
using DLL.NET50.DB.PIVAS.ORM.Service;
using DLL.NET60.DB.MS.Entity.DTO;
using DLL.Standard.Infrastructure.Log;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace DLL.NET.DB.MS.Drugs.CRUD.Repository
{
    public interface IMSUpOrDownDrugRepository
    {
        bool LocalBackupToMS();

        bool MSToLocalBackup();

        //bool CopyedToLocalBackup();

        //bool RemoteBackupToLocalBackup();

        //bool LocalBackupToRemoteBackup();
    }

    public class CMSUpOrDownDrugRepository : IMSUpOrDownDrugRepository
    {
        //定义变量

        private IMSDrugsRepository ms_DrugsRepository;
        private ILocalDrugsRepository local_DrugsRepository;

        private IPivasDrugsService _pivasDrugsService;

        public CMSUpOrDownDrugRepository(
            IMSDrugsRepository msDrugs,
            ILocalDrugsRepository localDrugs,

            IPivasDrugsService pivasDrugsService
            )
        {
            ms_DrugsRepository = msDrugs;
            local_DrugsRepository = localDrugs;

            _pivasDrugsService = pivasDrugsService;
        }

        public int AddDrugCount = 0;
        public int UpdateDrugCount = 0;

        private List<DTO_adi_dic_drug> lMS_Drugs = new List<DTO_adi_dic_drug>();
        private List<DTO_adi_dic_drug> lLocalDrugs = new List<DTO_adi_dic_drug>();
        private List<DTO_adi_dic_drug> lRemoteBackupDrugs = new List<DTO_adi_dic_drug>();
        private List<DTO_adi_dic_drug> lCopyedDrugs = new List<DTO_adi_dic_drug>();

        /// <summary>
        /// 采用Socket方式，测试服务器连接
        /// </summary>
        /// <param name="host">服务器主机名或IP</param>
        /// <param name="port">端口号</param>
        /// <param name="millisecondsTimeout">等待时间：毫秒</param>
        /// <returns></returns>
        public static bool TestConnection(string host, int port, int millisecondsTimeout)
        {
            TcpClient client = new TcpClient();
            try
            {
                var ar = client.BeginConnect(host, port, null, null);
                ar.AsyncWaitHandle.WaitOne(millisecondsTimeout);
                return client.Connected;
            }
            catch (Exception e)
            {
                LogHelper.Error(e.Message);
                return false;                 //throw e;
            }
            finally
            {
                client.Close();
            }
        }

        #region adi_used_drugs-adi_used_drugs

        #region MS-Local 两个数据库之间的药品信息传递

        public bool LocalBackupToMS()
        {
            try
            {
                LogHelper.Debug("从mssavedDrugs库获取数据添加到 msrobot:adi_used_drug 数据库");
                System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
                stopwatch.Start(); //  开始监视代码

                lMS_Drugs = ms_DrugsRepository.GetDrugs();
                lLocalDrugs = local_DrugsRepository.GetDrugs();

                List<DTO_adi_dic_drug> lNeedAdd = new List<DTO_adi_dic_drug>();
                List<DTO_adi_dic_drug> lNeedModify = new List<DTO_adi_dic_drug>();
                GetNeedSaveDrugs_LocalBackupToMS(ref lNeedAdd, ref lNeedModify);

                InsertDataToDefinebaseRepository(ms_DrugsRepository, lNeedAdd);
                UpdateDataToDefinebaseRepository(ms_DrugsRepository, lNeedModify);

                LogHelper.Debug("从msSaveDrugs.aid_dic_drugs添加到MS.aid_dic_drugs表中的药品数量=" + lNeedAdd.Count().ToString());
                LogHelper.Debug("从msSaveDrugs.aid_dic_drugs更新到MS.aid_dic_drugs表中的药品数量=" + lNeedModify.Count().ToString());

                LogHelper.Debug("添加药品到MS.aid_dic_drugs    用时=" + GetUsedTotalTime(stopwatch).ToString());
                return true;
            }
            catch (Exception e)
            {
                LogHelper.Warn("异常信息" + e.Message);
                return false;
                throw;
            }
        }

        //将本地备份的数据，上传到服务器
        public bool MSToLocalBackup()
        {
            try
            {
                LogHelper.Debug("从msrobot获取数据添加到 msSaveDrugs:adi_used_drug ");
                System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
                stopwatch.Start(); //  开始监视代码

                lMS_Drugs = ms_DrugsRepository.GetDrugs();
                lLocalDrugs = local_DrugsRepository.GetDrugs();

                List<DTO_adi_dic_drug> lNeedAdd = new List<DTO_adi_dic_drug>();
                List<DTO_adi_dic_drug> lNeedModify = new List<DTO_adi_dic_drug>();
                GetNeedSaveDrugs_msRobotToLocalBackup(ref lNeedAdd, ref lNeedModify);

                InsertDataToDefinebaseRepository(local_DrugsRepository, lNeedAdd);
                UpdateDataToDefinebaseRepository(local_DrugsRepository, lNeedModify);
                LogHelper.Debug("从MS.aid_dic_drugs添加到msSaveDrugs.aid_dic_drugs表中的药品数量=" + lNeedAdd.Count().ToString());
                LogHelper.Debug("从MS.aid_dic_drugs更新到msSaveDrugs.aid_dic_drugs表中的药品数量=" + lNeedModify.Count().ToString());

                LogHelper.Debug("添加药品到msSaveDrugs.aid_dic_drugs    用时=" + GetUsedTotalTime(stopwatch).ToString());
                return true;
            }
            catch (Exception e)
            {
                LogHelper.Warn("异常信息" + e.Message);
                return false;
                throw;
            }
        }

        #endregion MS-Local 两个数据库之间的药品信息传递

        #region copy-> msSaveDrugs

        //public bool CopyedToLocalBackup()
        //{
        //    try
        //    {
        //        LogHelper.Debug("开始添加数据到 msSaveDrugs:adi_used_drug ");
        //        System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
        //        stopwatch.Start(); //  开始监视代码

        //        lLocalDrugs = local_DrugsRepository.GetDrugs();
        //        lCopyedDrugs = copyed_DrugsRepository.GetDrugs();

        //        List<DTO_adi_dic_drug> lNeedAdd = new List<DTO_adi_dic_drug>();
        //        List<DTO_adi_dic_drug> lNeedModify = new List<DTO_adi_dic_drug>();
        //        GetNeedSaveDrugs_CopyToLocalBackup(ref lNeedAdd, ref lNeedModify);

        //        InsertDataToDefinebaseRepository(local_DrugsRepository, lNeedAdd);
        //        UpdateDataToDefinebaseRepository(local_DrugsRepository, lNeedModify);

        //        LogHelper.Debug("从Copy添加到msSaveDrugs.aid_dic_drugs表中的药品数量=" + lNeedAdd.Count().ToString());
        //        LogHelper.Debug("从Copy更新到msSaveDrugs.aid_dic_drugs表中的药品数量=" + lNeedModify.Count().ToString());
        //        LogHelper.Debug("添加药品到msSaveDrugs.aid_dic_drugs   用时=" + GetUsedTotalTime(stopwatch).ToString());

        //        return true;
        //    }
        //    catch (Exception e)
        //    {
        //        LogHelper.Warn("异常信息" + e.Message);
        //        return false;
        //        throw;
        //    }
        //}

        //public bool CopyedToMS()
        //{
        //    try
        //    {
        //        LogHelper.Debug("开始添加数据到 msSaveDrugs:adi_used_drug ");
        //        System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
        //        stopwatch.Start(); //  开始监视代码

        //        lMS_Drugs = ms_DrugsRepository.GetDrugs();
        //        lCopyedDrugs = copyed_DrugsRepository.GetDrugs();

        //        List<DTO_adi_dic_drug> lNeedAdd = new List<DTO_adi_dic_drug>();
        //        List<DTO_adi_dic_drug> lNeedModify = new List<DTO_adi_dic_drug>();
        //        GetNeedSaveDrugs_CopyToMS(ref lNeedAdd, ref lNeedModify);

        //        InsertDataToDefinebaseRepository(ms_DrugsRepository, lNeedAdd);
        //        UpdateDataToDefinebaseRepository(ms_DrugsRepository, lNeedModify);

        //        LogHelper.Debug("从Copy添加到msSaveDrugs.aid_dic_drugs表中的药品数量=" + lNeedAdd.Count().ToString());
        //        LogHelper.Debug("从Copy更新到msSaveDrugs.aid_dic_drugs表中的药品数量=" + lNeedModify.Count().ToString());
        //        LogHelper.Debug("添加药品到msSaveDrugs.aid_dic_drugs   用时=" + GetUsedTotalTime(stopwatch).ToString());

        //        return true;
        //    }
        //    catch (Exception e)
        //    {
        //        LogHelper.Warn("异常信息" + e.Message);
        //        return false;
        //        throw;
        //    }

        //}

        #endregion copy-> msSaveDrugs

        #region msSaveDrugs-remotebackup

        //public bool RemoteBackupToLocalBackup()
        //{
        //    try
        //    {
        //        LogHelper.Debug("开始添加数据到 msSaveDrugs:adi_used_drug ");
        //        System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
        //        stopwatch.Start(); //  开始监视代码

        //        lLocalDrugs = local_DrugsRepository.GetDrugs();
        //        lRemoteBackupDrugs = server_DrugsRepository.GetDrugs();
        //        List<DTO_adi_dic_drug> lNeedAdd = new List<DTO_adi_dic_drug>();
        //        List<DTO_adi_dic_drug> lNeedModify = new List<DTO_adi_dic_drug>();
        //        GetNeedSaveDrugs_RemoteBackupToLocalBackup(ref lNeedAdd, ref lNeedModify);

        //        InsertDataToDefinebaseRepository(local_DrugsRepository, lNeedAdd);
        //        UpdateDataToDefinebaseRepository(local_DrugsRepository, lNeedModify);
        //        LogHelper.Debug("从RemoteBackup添加到msSaveDrugs.aid_dic_drugs表中的药品数量=" + lNeedAdd.Count().ToString());
        //        LogHelper.Debug("从RemoteBackup更新到msSaveDrugs.aid_dic_drugs表中的药品数量=" + lNeedModify.Count().ToString());

        //        LogHelper.Debug("添加药品到msSaveDrugs.aid_dic_drugs    用时=" + GetUsedTotalTime(stopwatch).ToString());
        //        return true;
        //    }
        //    catch (Exception e)
        //    {
        //        LogHelper.Warn("异常信息" + e.Message);
        //        return false;
        //        throw;
        //    }
        //}

        //public bool LocalBackupToRemoteBackup()
        //{
        //    try
        //    {
        //        LogHelper.Debug("开始添加数据到 remotebackup:adi_used_drug ");
        //        System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
        //        stopwatch.Start(); //  开始监视代码

        //        lLocalDrugs = local_DrugsRepository.GetDrugs();
        //        lRemoteBackupDrugs = server_DrugsRepository.GetDrugs();
        //        List<DTO_adi_dic_drug> lNeedAdd = new List<DTO_adi_dic_drug>();
        //        List<DTO_adi_dic_drug> lNeedModify = new List<DTO_adi_dic_drug>();
        //        GetNeedSaveDrugs_LocalBackupToRemoteBackup(ref lNeedAdd, ref lNeedModify);

        //        InsertDataToDefinebaseRepository(server_DrugsRepository, lNeedAdd);
        //        UpdateDataToDefinebaseRepository(server_DrugsRepository, lNeedModify);
        //        LogHelper.Debug("从msSaveDrugs添加到RemoteBackup.aid_dic_drugs表中的药品数量=" + lNeedAdd.Count().ToString());
        //        LogHelper.Debug("从msSaveDrugs更新到RemoteBackup.aid_dic_drugs表中的药品数量=" + lNeedModify.Count().ToString());

        //        LogHelper.Debug("添加药品到RemoteBackup.aid_dic_drugs   用时=" + GetUsedTotalTime(stopwatch).ToString());
        //        return true;
        //    }
        //    catch (Exception e)
        //    {
        //        LogHelper.Warn("异常信息" + e.Message);
        //        return false;
        //        throw;
        //    }
        //}

        #endregion msSaveDrugs-remotebackup

        #region 获取需要保存的药品信息

        #region msrobot-msSaveDrugs

        private void GetNeedSaveDrugs_LocalBackupToMS(ref List<DTO_adi_dic_drug> lNeedAdddrugs, ref List<DTO_adi_dic_drug> lNeedModifydrugs)
        {
            //
            GetAddDrugsFromMSSaveDrugs(lLocalDrugs, lMS_Drugs, ref lNeedAdddrugs, ref lNeedModifydrugs);
        }

        private void GetNeedSaveDrugs_msRobotToLocalBackup(ref List<DTO_adi_dic_drug> lNeedAdddrugs, ref List<DTO_adi_dic_drug> lNeedModifydrugs)
        {
            GetNeedSaveedDrugs(lMS_Drugs, lLocalDrugs, ref lNeedAdddrugs, ref lNeedModifydrugs);
        }

        #endregion msrobot-msSaveDrugs

        #region copy -> msSaveDrugs

        private void GetNeedSaveDrugs_CopyToLocalBackup(ref List<DTO_adi_dic_drug> lNeedAdddrugs, ref List<DTO_adi_dic_drug> lNeedModifydrugs)
        {
            GetNeedSaveedDrugs(lCopyedDrugs, lLocalDrugs, ref lNeedAdddrugs, ref lNeedModifydrugs);
        }

        #endregion copy -> msSaveDrugs

        #region copy->msrobot

        private void GetNeedSaveDrugs_CopyToMS(ref List<DTO_adi_dic_drug> lNeedAdddrugs, ref List<DTO_adi_dic_drug> lNeedModifydrugs)
        {
            GetNeedSaveedDrugs(lCopyedDrugs, lMS_Drugs, ref lNeedAdddrugs, ref lNeedModifydrugs);
        }

        #endregion copy->msrobot

        #region msSaveDrugs-remotebackup

        private void GetNeedSaveDrugs_RemoteBackupToLocalBackup(ref List<DTO_adi_dic_drug> lNeedAdddrugs, ref List<DTO_adi_dic_drug> lNeedModifydrugs)
        {
            GetNeedSaveedDrugs(lRemoteBackupDrugs, lLocalDrugs, ref lNeedAdddrugs, ref lNeedModifydrugs);
        }

        private void GetNeedSaveDrugs_LocalBackupToRemoteBackup(ref List<DTO_adi_dic_drug> lNeedAdddrugs, ref List<DTO_adi_dic_drug> lNeedModifydrugs)
        {
            GetNeedSaveedDrugs(lLocalDrugs, lRemoteBackupDrugs, ref lNeedAdddrugs, ref lNeedModifydrugs);
        }

        #endregion msSaveDrugs-remotebackup

        private void GetNeedSaveedDrugs(List<DTO_adi_dic_drug> from, List<DTO_adi_dic_drug> to, ref List<DTO_adi_dic_drug> lNeedAdddrugs, ref List<DTO_adi_dic_drug> lNeedModifydrugs)
        {
            lNeedAdddrugs.Clear();
            lNeedModifydrugs.Clear();
            foreach (var drug in from)
            {
                //从msSaveDrugs 数据库中获取数据
                DTO_adi_dic_drug orgdrug = (DTO_adi_dic_drug)drug.Clone();
                DTO_adi_dic_drug hadExistDrug = new DTO_adi_dic_drug();
                //判断AC数据库中是否有同样的药品
                int have = JudgeDstWhetherHaveTheSameDrug(orgdrug, to, ref hadExistDrug);
                if (1 == have)
                {
                    //本地存储编辑过药品属性的药品已经存在
                    orgdrug.DRUG_CODE = hadExistDrug.DRUG_CODE;
                    lNeedModifydrugs.Add(orgdrug);
                }
                else if (2 == have)
                {
                    lNeedAdddrugs.Add(orgdrug);
                }
            }
        }

        private void GetAddDrugsFromMSSaveDrugs(List<DTO_adi_dic_drug> from,
            List<DTO_adi_dic_drug> to,
            ref List<DTO_adi_dic_drug> lNeedAdddrugs,
            ref List<DTO_adi_dic_drug> lNeedModifydrugs)
        {
            lNeedAdddrugs.Clear();
            lNeedModifydrugs.Clear();
            List<DTO_pivas_read_drugs> pivasDrugs = _pivasDrugsService.GetDrugs();
            foreach (var drug in from)
            {
                //从msSaveDrugs 数据库中获取数据
                DTO_adi_dic_drug orgdrug = (DTO_adi_dic_drug)drug.Clone();
                DTO_adi_dic_drug hadExistDrug = new DTO_adi_dic_drug();
                //判断AC数据库中是否有同样的药品
                int have = JudgeDstWhetherHaveTheSameDrug(orgdrug, to, ref hadExistDrug);
                if (1 == have)
                {
                    //msrobot ,存在药品名称，厂家，剂量，都相同的药，则用新的药品属性覆盖msrobot里面的药
                    orgdrug.DRUG_CODE = hadExistDrug.DRUG_CODE;

                    lNeedModifydrugs.Add(orgdrug);
                }
                else if (2 == have)
                {
                    //msrobot 本地不存在该药，判断pivas里面有没有相同药品编码的药
                    List<DTO_pivas_read_drugs> spivasdrugs = pivasDrugs.Where<DTO_pivas_read_drugs>(c => c.DRUG_CODE == orgdrug.DRUG_CODE).ToList();
                    bool isExist = _pivasDrugsService.IsExist(orgdrug.DRUG_CODE);
                    if (true == isExist)
                    {
                        //PIVAS 表里面存在相同药品编码的药，则可以直接添加到MSrobot数据库
                        lNeedAdddrugs.Add(orgdrug);
                    }
                }
                //返回0不用更新;
            }
        }

        #endregion 获取需要保存的药品信息

        #endregion adi_used_drugs-adi_used_drugs

        #region 公用私有函数函数

        private bool PropertyIsSet(DTO_adi_dic_drug drug)
        {
            if ((drug.SOLVENT_FLAG == null)
                || (drug.NEEDLE_TYPE == null)
                )
            {
                return false;
            }
            return true;
        }

        private int JudgeDstWhetherHaveTheSameDrug(DTO_adi_dic_drug orgDrug, List<DTO_adi_dic_drug> lDstDrugs, ref DTO_adi_dic_drug HadExistDrug)
        {
            bool iset = PropertyIsSet(orgDrug);
            if (false == iset)
            {
                LogHelper.Warn("药品属性没有设置，药品名称=" + orgDrug.DRUG_NAME);
                return 0;
            }
            List<DTO_adi_dic_drug> hasDrugs = lDstDrugs.Where(d => d.Drug_UniqueCode == orgDrug.Drug_UniqueCode).ToList();
            if (hasDrugs == null)
            {
                return 2;//不存在，需要添加
            }
            else
            {
                if (hasDrugs.Count == 0)
                {
                    return 2;//不存在，需要添加
                }
                else
                {
                    //只药存在就更新
                    if (orgDrug.updateTime > hasDrugs[0].updateTime)
                    {
                        //源数据 比目的数据中的新，可以更新；
                        HadExistDrug = hasDrugs[0];
                        return 1;
                    }
                    else
                    {
                        return 0;
                    }
                }
            }
        }

        private double GetUsedTotalTime(Stopwatch stopwatch)
        {
            stopwatch.Stop(); //  停止监视
            TimeSpan timeSpan = stopwatch.Elapsed; //  获取总时间
            double milliseconds = timeSpan.TotalMilliseconds;  //  毫秒数
            return milliseconds;
        }

        #endregion 公用私有函数函数

        #region mysql+ef 执行Command命令

        //SELECT *from adi_advice_drug WHERE DRUG_CODE='00582600 ' AND	to_days(CREATE_DATE) = to_days(now());
        //ExecuteSqlCommand()更适合用来执行创建、插入、更新、删除操作
        //SqlQuery()则会返回查询到的结果，并将结果保存在数据实体中，所以SqlQuery()更适合执行查询操作。

        private bool InsertDataToDefinebaseRepository(IBaseDrugsRepository baseRepository, List<DTO_adi_dic_drug> lInsertDrugs)
        {
            if (lInsertDrugs.Count == 0)
            {
                return true;
            }
            //string sql = GetInsertSqlCommandStr(tableName, lInsertDrugs); //"SELECT * from DTO_adi_dic_drug";
            //baseRepository.ExecuteSqlCommand(sql);
            AddDrugsToUsedTable(baseRepository, lInsertDrugs);
            return true;
        }

        private bool UpdateDataToDefinebaseRepository(IBaseDrugsRepository baseRepository, List<DTO_adi_dic_drug> lInsertDrugs)
        {
            if (lInsertDrugs.Count == 0)
            {
                return true;
            }
            UpdateDrugsToUsedTable(baseRepository, lInsertDrugs);
            return true;
        }

        private void AddDrugsToUsedTable(IBaseDrugsRepository baseRepository, List<DTO_adi_dic_drug> ldrugs)
        {
            baseRepository.AddRangeDrugs(ldrugs);
        }

        private void UpdateDrugsToUsedTable(IBaseDrugsRepository baseRepository, List<DTO_adi_dic_drug> ldrugs)
        {
            baseRepository.UpdateRangeDrugs(ldrugs);
        }

        #endregion mysql+ef 执行Command命令
    }
}